package com.ecarx.vhaltests.hy11.testcases.drivemode;



import static vendor.ecarx.xma.automotive.vehicle.V2_0.ECarXVehicleProperty.DRIVEMODE_MODE_SET;
import vendor.ecarx.xma.automotive.vehicle.V2_0.DriveMode;


import android.car.VehicleAreaType;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;

import androidx.test.platform.app.InstrumentationRegistry;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VehicleConstants;
import com.ecarx.vhaltests.VhalUnitTestBase;
import com.ecarx.xui.adaptapi.car.IWrapper;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class DriveModeSetTest extends VhalUnitTestBase {
    private CarPropertyManager.CarPropertyEventCallback propertyCbk;
    private static IpcpClient ipcpClient = new IpcpClient();
    ;
    private boolean isFirstCbk;
    private static final int AREA_ID = VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;

    private int cbkValue;
    private final Object cbkLock = new Object();


    @BeforeClass
    public static void testInit() {
        setAvailable(true);
        Assert.assertTrue(isAvail());
    }

    @Test
    public void test001_SetDRIVE_MODE_SELECTION_ECO() {
        testSetGet(DriveMode.DRIVE_MODE_SELECTION_ECO);
    }

    @Test
    public void test002_SetDRIVE_MODE_SELECTION_COMFORT() {
        testSetGet(DriveMode.DRIVE_MODE_SELECTION_COMFORT);
    }

    @Test
    public void test003_SetDRIVE_MODE_SELECTION_DYNAMIC() {
        testSetGet(DriveMode.DRIVE_MODE_SELECTION_DYNAMIC);
    }
 
    @Test
    public void test004_Set_DRIVE_MODE_SELECTION_INDIVIDUAL() {
        testSetGet(DriveMode.DRIVE_MODE_SELECTION_INDIVIDUAL);
    }
    
    @Test
    public void test005_Set_DRIVE_MODE_SELECTION_OFFROAD() {
        testSetGet(DriveMode.DRIVE_MODE_SELECTION_OFFROAD);
    }

    @Test
    public void test006_Set_DRIVE_MODE_SELECTION_ROCK() {
        testSetGet(DriveMode.DRIVE_MODE_SELECTION_ROCK);
    }

    @Test
    public void test007_SetDmFuncDriveModeSelectUnAvail() {
        setAvailable(false);
        Assert.assertFalse(isAvail());
    }

    @Test
    public void test008_SetDRIVE_MODE_SELECTION_ERROR() {
        setValue(DriveMode.DRIVE_MODE_SELECTION_ERROR);
    }

    @Test
    public void test09_SetDmFuncDriveModeSelectChangeToDyno() {
        testSetGet(DriveMode.DRIVE_MODE_SELECTION_DYNAMIC);
        mockCarMode(VehicleConstants.CAR_MODE_DYNO);
        delay();
        Assert.assertEquals(DriveMode.DRIVE_MODE_SELECTION_COMFORT, getValue());
    }

    private static void setAvailable(boolean isAvail) {
        int ccSvcId = 135;
        int[] ccOperIds = {200};

        int cemSvcId = 37;
        int[] cemOperIds = {999};

        ipcpClient.setConfig(ccSvcId, ccOperIds);
        ipcpClient.setConfig(cemSvcId, cemOperIds);

        int[] configs = {13, 220};
        int[] values = {4, 10};
        boolean ccRet = ipcpClient.setCarconfigSignal(ccSvcId, ccOperIds[0], configs, values);
        Assert.assertTrue(ccRet);

        String[] cems = {"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts"};
        int[] cemValues = {isAvail ? VehicleConstants.CAR_MODE_NOMAL : VehicleConstants.CAR_MODE_TRANSPORT, VehicleConstants.USG_MODE_DRIVING};
        boolean cemRet = ipcpClient.setCEMSignal(cemSvcId, cemOperIds[0], cems, cemValues);
        Assert.assertTrue(cemRet);
    }

    private static void mockCarMode(int mode) {
        int cemSvcId = 37;
        int[] cemOperIds = {999};
        ipcpClient.setConfig(cemSvcId, cemOperIds);
        String[] cems = {"vehModMngtGlbSafe1CarModSts1", "vehModMngtGlbSafe1UsgModSts"};
        int[] cemValues = {mode, VehicleConstants.USG_MODE_DRIVING};
        boolean cemRet = ipcpClient.setCEMSignal(cemSvcId, cemOperIds[0], cems, cemValues);
        Assert.assertTrue(cemRet);
    }

    private void testSetGet(int value) {
        setValue(value);
        Assert.assertEquals(value, getValue());
    }

    private void setValue(int value) {
        setAvailable(true);
        delay();
        mCarPropertyMgr.setIntProperty(DRIVEMODE_MODE_SET, AREA_ID, value);
    }

    private static int getValue() {
        delay();
        return mCarPropertyMgr.getIntProperty(DRIVEMODE_MODE_SET, AREA_ID);
    }

    private static boolean isAvail() {
        delay();
        return mCarPropertyMgr.isPropertyAvailable(DRIVEMODE_MODE_SET, AREA_ID);
    }

   
    private void lock() {
        try {
            synchronized (cbkLock) {
                cbkLock.wait(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void unLock() {
        synchronized (cbkLock) {
            cbkLock.notify();
        }
    }

}
